import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import { message, Modal, Progress } from 'antd';
import PropTypes from 'prop-types';
import openFolder from './../../../../asserts/opn_cur_folder.png';
import continueIcon from '../../../../asserts/upload_continue.png';
import cancelIcon from '../../../../asserts/upload_cancel.png';
import pauseIcon from './../../../../asserts/upload_pause.png';
import otherIcon from './../../../../asserts/ic_other_v1.png';
import reloadIcon from './../../../../asserts/error_reload.png';
import ScrollArea from 'react-scrollbar';
import Arrow from '../../../common/Arrow';
import { ExclamationCircleOutlined } from '@ant-design/icons';
import 'antd/lib/progress/style';
import 'antd/lib/message/style';
import 'antd/lib/modal/style';
import './index.less';
import { bytesToSize, eleStatus } from '../../../../utils/commonUtils';
import {
  removeFileByIndex,
  setPartFileUploadAttribute
} from '../../../../redux/actions/fileUploadAttribute';
import {
  getPage,
  removePage,
  setPage,
} from '../../../../utils/storageUtils';
import { cancelFastDFSUploading, partUploadFastDFS, preChunkUploadFastDFS } from '../../../../api';
import {
  COMMON_SUCCESS_STATE,
  ERROR_UPLOADING,
  PAUSED_RESOLVE,
  PAUSED_UPLOADING
} from '../../../../constant';

const { confirm } = Modal;

class TransferList extends PureComponent {

  static propTypes = {
    transferVisible: PropTypes.bool,
    uploadList: PropTypes.object,
    removeFileByIndex: PropTypes.func,
    setPartFileUploadAttribute: PropTypes.func,
    folder: PropTypes.object,
    category: PropTypes.object
  };

  state = {
    activeIndex: 0,
    uploadedFileCount: 0
  };

  // 上传
  upload = (key, cur) => {
    this.preUpload(key, cur);
  };

  // 取消文件解析
  cancelUpload = (key) => {
    const { uploadList } = this.props;
    if (uploadList[key].preUploading) {
      // 文件解析，中断解析
      setPage(key + PAUSED_RESOLVE, true);
    }
    // 移出当前解析项
    const { removeFileByIndex } = this.props;
    removeFileByIndex(key);
  };

  // 取消正在上传的文件
  cancelUploading = (key, cur, event) => {
    const { removeFileByIndex } = this.props;
    event.stopPropagation();
    confirm({
      title: '警告!',
      icon: <ExclamationCircleOutlined/>,
      content: '是否需要取消正在上传的任务',
      async onOk () {
        // 发送请求删除临时文件夹
        // let { code } = await cancelLocalUploading({fileMd5: cur.uploadParams.file.fileMd5, localPath: cur.localPath})
        let { code } = await cancelFastDFSUploading({
          fileMd5: cur.uploadParams.file.fileMd5,
          localPath: cur.localPath
        });
        if (code === COMMON_SUCCESS_STATE) {
          // 移出列表项
          removeFileByIndex(key);
          message.success('删除成功');
        } else {
          message.error('未知异常，删除失败');
        }
      }
    });
  };

  // 重新上传错误文件
  reloadUploading = async (key, cur, event) => {
    event.stopPropagation()
    // 移出错误标记
    removePage(key + ERROR_UPLOADING)
    let { code } = await cancelFastDFSUploading({
      fileMd5: cur.uploadParams.file.fileMd5,
      localPath: cur.localPath
    });
    if (code === COMMON_SUCCESS_STATE) {
      // 移出列表项
      removeFileByIndex(key);
      // 再次点击文件上传
      this.upload(key, cur)
    } else {
      message.error('重新上传失败');
    }
  }

  // 切换上传状态
  toggleUploadStatus = (key, cur, flag, event) => {
    event.stopPropagation();
    if (!flag) {
      // 继续下载
      this.preUpload(key, cur);
    }
    setPage(key + PAUSED_UPLOADING, flag);
  };

  // 确认需要上传的有哪些分片，支持断续上传
  preUpload = async (key, cur) => {
    const { setPartFileUploadAttribute, category } = this.props;
    const { uploadParams } = cur;
    // requestUrl,返回可以上传的分片队列
    // let { data, code } = await preChunkUploadLocal(uploadParams);
    let {
      data,
      code
    } = await preChunkUploadFastDFS(uploadParams);
    if (code === COMMON_SUCCESS_STATE) {

      if (data.isAPass) {
        message.success('秒传成功');
        setPartFileUploadAttribute({
          [key]: {
            uploaded: true,   // 让进度条消失
            uploading: false
          }
        });
        // 移出store中的暂停标记
        removePage(key + PAUSED_UPLOADING)
        // 刷新页面
        category.target.click()
        return
      }

      // 过滤出还需要上传的分片
      let uploadChunk = data.chunks.filter((item) => item.status === 'pending');
      // 计算已经上传的进度
      let uploadPercent = (data.uploaded / data.total * 100).toFixed(2);
      setPartFileUploadAttribute({
        [key]: {
          uploadPercent
        }
      });
      // 判断文件是否已经上传成功
      if (uploadPercent === 100) {
        message.success('上传成功');
        setPartFileUploadAttribute({
          [key]: {
            uploaded: true,   // 让进度条消失
            uploading: false
          }
        });
        // 移出store中的暂停标记
        removePage(key + PAUSED_UPLOADING);
        // 刷新页面
        category.target.click()
      } else {
        setPartFileUploadAttribute({
          [key]: {
            uploaded: false,
            uploading: true
          }
        });

        // 进行分片上传
        this.handlePartUpload(key, cur, uploadChunk, data.folderId, data.localPath);
      }
    } else {
      message.error('请求错误');
    }
  };

  // 正式上传分片数据
  // eslint-disable-next-line no-unused-vars
  handlePartUpload = async (key, cur, uploadChunk, folderId, localPath) => {
    const { setPartFileUploadAttribute, category } = this.props;
    // 遍历uploadList数据
    for (const item of uploadChunk) {
      // 查询当前是否为暂停状态
      if (getPage(key + PAUSED_UPLOADING) || getPage(key + ERROR_UPLOADING)) {
        return;
      }
      // 取出分片的基本属性
      let {
        fileMd5,
        chunkMd5,
        chunk,
        start,
        end,
        originalName
      } = item;
      let formData = new FormData(),
        // 将当前分片的ArrayBuffer加入到Blob中
        blob = new Blob([cur.arrayBufferData[chunk - 1].currentBuffer], { type: 'application/octet-stream' });
      // let params = `fileMd5=${fileMd5}&chunkMd5=${chunkMd5}&chunk=${chunk}&start=${start}&end=${end}&chunks=${this.state.arrayBufferData.length}`
      formData.append('fileMd5', fileMd5);
      formData.append('chunkMd5', chunkMd5);
      formData.append('chunk', chunk);
      formData.append('start', start);
      formData.append('end', end);
      formData.append('originalName', originalName);
      formData.append('folderId', folderId);
      // 上传远程FastDFS无需设置
      // formData.append('localPath', localPath)
      formData.append('contentType', cur.contentType);
      formData.append('fileSize', cur.fileSize);
      // 文件对目录选择的路径，文件选择为空
      formData.append('webkitRelativePath', cur.webkitRelativePath);
      const { length } = cur.arrayBufferData;
      formData.append('chunks', length);
      formData.append('chunkFile', blob, chunkMd5);

      // let { code, data } = await partUploadLocal(formData);
      let {
        code,
        data,
        msg
      } = await partUploadFastDFS(formData);
      if (code === COMMON_SUCCESS_STATE) {
        let {
          chunks,
          isComplete,
          complete
        } = data;
        // 计算上传速度
        let uploadPercent = Number((complete / chunks * 100).toFixed(2));
        setPartFileUploadAttribute({
          [key]: {
            uploadPercent,
            uploading: true
          }
        });
        if (isComplete) {
          // 设置上传数目
          this.setState((state) => {
            let count = state.uploadedFileCount;
            count++;
            return {
              uploadedFileCount: count
            };
          });
          // 调用验证api
          this.checkUpload();
          message.success('上传成功');
          setPartFileUploadAttribute({
            [key]: {
              uploading: false,
              uploaded: true
            }
          });
          // 移出store中的暂停标记
          removePage(key + PAUSED_UPLOADING);
          // 刷新页面
          category.target.click()
        }
      } else {
        message.error(msg);
        // 设置错误标记
        setPage(key + ERROR_UPLOADING, '服务器错误')
        // 设置上传数目
        this.setState({
          uploadedFileCount: 0
        });
        setPartFileUploadAttribute({
          [key]: {
            uploading: false,
            uploadPercent: 0
          }
        });
        // 移出store中的暂停标记
        removePage(key + PAUSED_UPLOADING);
      }
    }
  };

  // 验证上传结果
  checkUpload = () => {
    console.log('验证分片上传结果');
  };

  render () {
    const {
      activeIndex,
      uploadedFileCount
    } = this.state;
    const {
      transferVisible,
      uploadList
    } = this.props;
    return (
      <div onClick={(event) => {
        event.stopPropagation();
      }}
      className='transfer_list'
      style={{ display: transferVisible ? 'block' : 'none' }}>
        <Arrow direct='top'/>
        <div className="transfer_list_left">
          <p className="transfer_list_left_title">传输列表</p>
          <ul>
            <li onClick={(event) => {
              event.stopPropagation();
              this.setState({ activeIndex: 0 });
            }
            } className={activeIndex === 0 ? 'active' : ''}>文件上传 ({uploadedFileCount})
            </li>
            <li onClick={(event) => {
              event.stopPropagation();
              this.setState({ activeIndex: 1 });
            }
            } className={activeIndex === 1 ? 'active' : ''}>文件下载 (0)
            </li>
          </ul>
        </div>
        <div className="transfer_list_right">
          <div style={{ display: activeIndex === 0 ? 'block' : 'none' }}
            className="transfer_list_right_upload transfer_list_right_common">
            <p className="transfer_list_right_upload_title">
              <span>
                {
                  `上传完成 (${uploadedFileCount}/${Object.keys(uploadList).length})`
                }
              </span>
              <span>清空失败</span>
            </p>
            <div className="transfer_list_right_upload_content">
              {/* 固定ScrollArea区域的高度即可达到滚动的效果，并且该父元素不能撑开，必须固定为当前高度*/}
              <ScrollArea
                smoothScrolling
                speed={0.8}
                className="area"
              >
                <ul>
                  {
                    Object.keys(uploadList)
                      .map((key) => {
                        let cur = uploadList[key];
                        return (
                          <li key={key} className="upload_box">
                            <div className="upload_left">
                              <img src={otherIcon} alt=""/>
                              <div className="upload_info_tro">
                                <p className="upload_name">
                                  {
                                    cur.fileName
                                  }
                                </p>
                                <Progress style={{ display: cur.preUploading ? 'block' : 'none' }}
                                  className='resolveProgress'
                                  strokeWidth='4px' percent={cur.preUploadPercent}
                                  status={cur.preUploadPercent === 100 ? 'success' : 'active'}/>
                                <Progress style={{ display: cur.uploading ? 'block' : 'none' }}
                                  className='uploadProgress'
                                  strokeWidth='4px' percent={cur.uploadPercent}
                                  status={cur.uploaded === true ? 'success' : 'active'}/>
                                <p className="upload_size">
                                  <span  style={{ display: getPage(key + ERROR_UPLOADING)? 'block': 'none', color: 'red', marginRight: '14px', fontSize: '12px' }}>
                                    {
                                      getPage(key + ERROR_UPLOADING)
                                    }
                                  </span>
                                  {
                                    bytesToSize(cur.fileSize)
                                  }
                                  <span style={eleStatus(cur.preUploading)} className="resolve">
                                文件解析中...
                                  </span>
                                </p>
                              </div>
                            </div>
                            <div className="upload_right">
                              {/* 解析完成上传按钮*/}
                              <img
                                style={{ display: !getPage(key + ERROR_UPLOADING) && cur.preUploadPercent === 100 && !cur.uploading && !cur.uploaded ? 'block' : 'none' }}
                                onClick={() => this.upload(key, cur)}
                                src={continueIcon} alt=""/>
                              {/* 取消上传，或者解析途中取消*/}
                              <img
                                style={{ display: !getPage(key + ERROR_UPLOADING) &&  cur.preUploading || (cur.preUploadPercent === 100 && !cur.uploading && !cur.uploaded) ? 'block' : 'none' }}
                                onClick={() => this.cancelUpload(key)}
                                src={cancelIcon} alt=""/>
                              {/* 正在上传*/}
                              <div style={eleStatus(cur.uploading)} className="uploading_btn">
                                {/* 继续上传按钮*/}
                                <img
                                  onClick={(event) => this.toggleUploadStatus(key, cur, false, event)}
                                  style={{ display: getPage(key + PAUSED_UPLOADING) ? 'block' : 'none' }}
                                  src={continueIcon} alt=""/>
                                {/* 暂停按钮*/}
                                <img
                                  onClick={(event) => this.toggleUploadStatus(key, cur, true, event)}
                                  style={{ display: getPage(key + PAUSED_UPLOADING) ? 'none' : 'block' }}
                                  src={pauseIcon} alt=""/>
                                {/* 取消上传按钮 点击按钮取消正在上传的任务*/}
                                <img onClick={(event) => this.cancelUploading(key, cur, event)}
                                  src={cancelIcon} alt=""/>
                              </div>
                              {/* error*/}
                              <img onClick={(event) => this.reloadUploading(key, cur, event)} style={{display: getPage(key + ERROR_UPLOADING)? 'block': 'none'}} src={reloadIcon} alt=""/>
                              {/* 上传完成*/}
                              <img style={eleStatus(cur.uploaded)} className="uploaded_btn"
                                src={openFolder} alt=""/>
                            </div>
                          </li>
                        );
                      })
                  }
                </ul>
                <p className="tip">
                  - 仅展示本次上传任务 -
                </p>
              </ScrollArea>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

export default connect(
  (state) => ({
    uploadList: state.fileUploadAttribute,
    folder: state.folder,
    transferVisible: state.transferVisible,
    category: state.category
  }), {
    setPartFileUploadAttribute,
    removeFileByIndex
  }
)(TransferList);
